VS Code 下载慢的解决办法

将下载链接的域名改为 vscode.cdn.azure.cn,这是微软在国内的 CDN 地址。

例如 https://az764295.vo.msecnd.net/stable/899d46d82c4c95423fb7e10e68eba52050e30ba3/code_1.63.2-1639562499_amd64.deb
改为 https://vscode.cdn.azure.cn/stable/899d46d82c4c95423fb7e10e68eba52050e30ba3/code_1.63.2-1639562499_amd64.deb

可以使用下面的 Python 脚本进行下载:

1$ python vscode-download.py --os linux-deb-x64
2Request https://code.visualstudio.com/sha/download?build=stable&os=linux-deb-x64
3Redirect to https://az764295.vo.msecnd.net/stable/704ed70d4fd1c6bd6342c436f1ede30d1cff4710/code_1.77.3-1681292746_amd64.deb
4Redirect to https://vscode.cdn.azure.cn/stable/704ed70d4fd1c6bd6342c436f1ede30d1cff4710/code_1.77.3-1681292746_amd64.deb
5Download 88538392/88538392 bytes
6Done.
1#! /usr/bin/env python3
2# author: planc
3# e-mail: [email protected]
4# repo: https://github.com/hubenchang0515/Moe-Maid/blob/master/vscode-download.py
5
6import argparse
7import urllib.request
8import urllib.parse
9from pathlib import Path
10
11os_options: list[str] = [
12    "win32-x64-user",
13    "win32-user",
14    "win32-arm64-user",
15
16    "win32-x64",
17    "win32",
18    "win32-arm64",
19
20    "win32-x64-archive",
21    "win32-archive",
22    "win32-arm64-archive",
23
24    "cli-win32-x64",
25    "cli-x64",
26    "cli-arm64-x64",
27
28    "linux-deb-x64",
29    "linux-deb-armhf",
30    "linux-deb-arm64",
31
32    "linux-rpm-x64",
33    "linux-rpm-armhf",
34    "linux-rpm-arm64",
35
36    "linux-x64",
37    "linux-armhf",
38    "linux-arm64",
39
40    "cli-alpine-x64",
41    "cli-alpine-armhf",
42    "cli-alpine-arm64",
43
44    "darwin",
45    "darwin-arm64",
46    "darwin-universal",
47
48    "cli-darwin-x64",
49    "cli-darwin-arm64",
50]
51
52build_options: list[str] = [
53    "stable",
54    "insider"
55]
56
57class RedirectHandler(urllib.request.HTTPRedirectHandler):
58    def __init__(self, cdn) -> None:
59        super().__init__()
60        self.__cdn = cdn
61
62    def redirect_request(self, req, fp, code, msg, headers, newurl):
63        print(f"Redirect to {newurl}")
64        parts = urllib.parse.urlparse(newurl)
65        parts = parts._replace(netloc=self.__cdn)
66        newurl = parts.geturl()
67        print(f"Redirect to {newurl}")
68        return urllib.request.Request(newurl)
69
70if __name__ == "__main__":
71    build_options:str = "\n\t".join(build_options)
72    os_options:str = "\n\t".join(os_options)
73    parser = argparse.ArgumentParser(description="Download VS Code with CDN", 
74                                        epilog=f"build options:\n\t{build_options}\n\nos options:\n\t{os_options}\n",
75                                        formatter_class=argparse.RawTextHelpFormatter)
76    parser.add_argument("--os", required=True, help="operating system")
77    parser.add_argument("--build", required=False, help="build type, default 'stable'", default="stable")
78    parser.add_argument("--cdn", required=False, help="CDN url, default 'vscode.cdn.azure.cn'", default="vscode.cdn.azure.cn")
79    parser.add_argument("--proxy", required=False, help="proxy, default None")
80    args = parser.parse_args()
81
82    if args.proxy is None:
83        proxies = None
84    else:
85        proxies = {
86            "http": args.proxy,
87            "https": args.proxy,
88            "socks5": args.proxy,
89        }
90
91    proxy_handler = urllib.request.ProxyHandler(proxies=proxies)
92    redirect_handler = RedirectHandler(args.cdn)
93    opener = urllib.request.build_opener(proxy_handler, redirect_handler)
94
95    params = urllib.parse.urlencode({'build': args.build, 'os': args.os})
96    url:str = f"https://code.visualstudio.com/sha/download?{params}"
97    print(f"Request {url}")
98    
99    with opener.open(url) as response:
100        parts = urllib.parse.urlparse(response.geturl())
101        path = Path(parts.path)
102        total_bytes:int = int(response.getheader('Content-Length'))
103        done_bytes:int = 0
104        with open(path.name, mode="wb") as fp:
105            while done_bytes < total_bytes:
106                data = response.read(4*1024)
107                if data is None:
108                    break
109                fp.write(data)
110                done_bytes += len(data)
111                print(f"Download {done_bytes}/{total_bytes} bytes", end="\r")
112            print("\nDone.")